using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Security.Principal;
using System.Threading;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using SalesPoint.Commands;
using SalesPoint.Model;
using SalesPoint.Security;
using SalesPoint.Views;
using Xtensive.Orm;
using Xtensive.Orm.Security;

namespace SalesPoint.ViewModels
{
  public class MainWindowViewModel : ViewModelBase
  {
    private readonly List<CommandViewModel> commands;
    private readonly ObservableCollection<WorkspaceViewModel> workspaces;
    private DelegateCommand logoutCommand;

    public string ApplicationTitle { get; private set; }

    public List<CommandViewModel> Commands
    {
      get { return commands; }
    }

    public ObservableCollection<WorkspaceViewModel> Workspaces
    {
      get { return workspaces; }
    }

    public ICommand LogoutCommand
    {
      get
      {
        if (logoutCommand != null)
          return logoutCommand;

        logoutCommand = new DelegateCommand(ExecuteLogout);
        return logoutCommand;
      }
    }

    public event EventHandler<EventArgs> Logout;

    private void ExecuteLogout()
    {
      InvokeLogout(new EventArgs());
    }

    private void InvokeLogout(EventArgs e)
    {
      var handler = Logout;
      if (handler != null)
        handler(this, e);
    }

    private void OpenWorkspace(WorkspaceViewModel viewModel, UserControl view)
    {
      view.DataContext = viewModel;
      viewModel.View = view;
      viewModel.Close += CloseWorkspace;
      workspaces.Add(viewModel);
      var collectionView = CollectionViewSource.GetDefaultView(Workspaces);
      if (collectionView != null)
        collectionView.MoveCurrentTo(viewModel);
    }

    private void CloseWorkspace(object sender, System.EventArgs e)
    {
      var workspace = (WorkspaceViewModel) sender;
      if (!workspaces.Contains(workspace))
        return;

      workspaces.Remove(workspace);
      workspace.Close -= CloseWorkspace;
    }

    private void OpenCustomers()
    {
      OpenWorkspace(new CustomerListViewModel(Session), new CustomerListView());
    }

    public bool CanOpenCustomers()
    {
      var context = Session.GetImpersonationContext();
      if (context == null)
        return false;
      return context.Permissions.Contains<Permission<Customer>>(p => p.CanRead);
    }

    private void OpenOrders()
    {
      OpenWorkspace(new OrderListViewModel(Session), new OrderListView());
    }

    public bool CanOpenOrders()
    {
      var context = Session.GetImpersonationContext();
      if (context == null)
        return false;
      return context.Permissions.Contains<OrderPermission>(p => p.CanRead);
    }

    private void OpenProducts()
    {
      OpenWorkspace(new ProductListViewModel(Session), new ProductListView());
    }

    public bool CanOpenProducts()
    {
      var context = Session.GetImpersonationContext();
      if (context == null)
        return false;
      return context.Permissions.Contains<Permission<Product>>(p => p.CanRead);
    }

    private void OpenEmployees()
    {
      OpenWorkspace(new EmployeeListViewModel(Session), new EmployeeListView());
    }

    public bool CanOpenEmployees()
    {
      var context = Session.GetImpersonationContext();
      if (context == null)
        return false;
      return context.Permissions.Contains<Permission<Employee>>(p => p.CanRead);
    }

    public MainWindowViewModel(Session session)
      : base(session)
    {
      var e = Session.GetImpersonationContext().Principal as Employee;
      ApplicationTitle= string.Format("SalesPoint: {0} {1}, {2}, {3}", e.FirstName, e.LastName, e.Title, e.Address.City);

      commands = new List<CommandViewModel>
                   {
                     new CommandViewModel(Session, "Customers", OpenCustomers, CanOpenCustomers),
                     new CommandViewModel(Session, "Orders", OpenOrders, CanOpenOrders),
                     new CommandViewModel(Session, "Products", OpenProducts, CanOpenProducts),
                     new CommandViewModel(Session, "Employees", OpenEmployees, CanOpenEmployees)
                   };

      workspaces = new ObservableCollection<WorkspaceViewModel>();
    }
  }
}